#pragma once

#include <QHostAddress>
#include <cstddef>
#include <cstdint>

#if 1
#include "struct.h" // agv include
#else
struct SecondLocateParams {
  int type{1}; // 1, 2
  int timeOut{10000};
  int binaryThreshold1;
  int maxRadius1;
  int binaryThreshold2;
  int maxRadius2;

  int real_radius{-1}; // -1 means do not use this, use scale
  int scale_times_1000{0};

  int reserved[4];
};

struct BackToZeroParams {
  int x_mm; // 毫米
  int y_mm; // 毫米
  int threshold;
};

struct CalculateMapAngleParams {
  int timeOut;
  int binaryThreshold;
  int maxRadius;
};

#endif

#include <QEvent>

#define QT_USER_EVENT_SHOWPIC ((QEvent::Type)(QEvent::User + 1))
#define QT_USER_EVENT_LOGLIST ((QEvent::Type)(QEvent::User + 2))


// 模块服务器端口
#define AGVMODULE_MODULE_SERVER_PORT ((uint16_t)(20011))

// 模块上位服务端口
#define AGVMODULE_UPPER_SERVER_PORT  ((uint16_t)(20012))

// Upper -> AGVModule Server
enum AGVModuleFrameTxId {
  AGVModuleFrameTxId_Unknow = 0,
  AGVModuleFrameTxId_StartManualLineMove = 1,   // 启动直线运动
  AGVModuleFrameTxId_StartManualRotateMove = 2, // 启动旋转运动
  AGVModuleFrameTxId_StopManualMove = 3, // 停止手动到直线、旋转运动

  // 结束系统
  AGVModuleFrameTxId_StopSystem,

  // 标定初始位置或重新标定初始位置
  AGVModuleFrameTxId_InitialPosition,

  // 满意标定结果, 结束初始位置标定
  AGVModuleFrameTxId_FinishInitialPosition,

  // 启动一次定位前, 启动MoveToTarget死循环线程
  AGVModuleFrameTxId_StartMoveToTargetThread,

  // 启动一次定位前, 回零
  AGVModuleFrameTxId_BackToZero,

  // 启动一次定位, SetTarget
  AGVModuleFrameTxId_StartFirstLocateSetTarget,

  // 启动一次二次定位计算, SecondLocate
  AGVModuleFrameTxId_StartSecondLocateCalc,

  // 关闭程序
  AGVModuleFrameTxId_QuitProgram,

  // 回门口
  AGVModuleFrameTxID_StartBackChange,

  // 计算地图角度
  AGVModuleFrameTxID_CalculateMapAngle,

  //! TODO
  AGVModuleFrameTxId_Max
};

struct agvmodule_tx_startmanuallinemove_data_t {
  uint32_t
      inc_pos_mm_times_1000; // 增量距离(始终正) 乘以1000 单位mm
  int32_t target_speed_mm_s_times_1000; // 速度(可负) 乘以1000下发 mm/s
};

struct agvmodule_tx_startmanualrotatemove_data_t {
  uint32_t
      inc_radius_times_1000000; // 增量距离(始终正) 乘以1000000下发 rad
  int32_t target_speed_radius_s_times_1000000; // 速度(可负) 乘以1000000下发 rad/s
};

struct agvmodule_tx_stopManualMove_data_t {
  uint32_t reserved; // 保留
};

struct agvmodule_tx_stopSystem_data_t {
  uint32_t reserved; // 保留
};

struct agvmodule_tx_initialPosition_data_t {
  int x_mm_times_1000; // 毫米 * 1000
  int y_mm_times_1000;
  int angle_times_1000000; // rad * 1000

  int timeout_ms{10000}; // 超时时间
};

struct agvmodule_tx_finishInitialPosition_data_t {
  uint32_t reserved; // 保留
};

struct agvmodule_tx_startMoveToTargetThread_data_t {
  uint32_t reserved; // 保留
};

// struct agvmodule_tx_backToZero_data_t {
//   uint32_t reserved; // 保留
// };
using agvmodule_tx_backToZero_data_t = BackToZeroParams;

struct agvmodule_tx_startFirstLocateSetTarget_data_t {
  int32_t x_mm_times_1000; // 毫米 * 1000
  int32_t y_mm_times_1000;
};

// struct agvmodule_tx_startSecondLocateCalc_data_t {
//   int binary_threshold{210};
//   int max_radius{100};
//   int timeout_ms{10000}; // 超时时间
// };
using agvmodule_tx_startSecondLocateCalc_data_t = SecondLocateParams;

struct agvmodule_tx_startBackChange_data_t {
  int32_t x_mm_times_1000; // 毫米 * 1000
  int32_t y_mm_times_1000;
};

struct agvmodule_tx_quitProgram_data_t {
  uint32_t reserved; // 保留
};

using agvmodule_tx_calculateMapAngle_data_t = CalculateMapAngleParams;

// AGVModule -> Upper Server
enum AGVModuleFrameRxId {
  AGVModuleFrameRxId_Unknow = 0,

  // 总体状态, 周期性下发
  AGVModuleFrameRxId_RegularInfo = 1,

  // 二次定位运动PLC指令，携带指令与相机坐标偏差（供显示）
  // 返回坐标0,0时, 表示二次定位结束
  AGVModuleFrameRxId_SecondLocateMovePlc,

  // 标定初始位置调用结束, 告诉上位机结束与标定结果,
  // 上位机要重新init的话, 调inititialPosition;
  // 上位机满意结果, 再调用finishInitialPosition
  AGVModuleFrameRxId_InitialPositionOnceOver,

  // 计算地图角度结果
  AGVModuleFrameRxId_CalculateMapAngleResult,

  AGVModuleFrameRxId_Max
};

struct agvmodule_rx_regularinfo_data_t {
  int32_t agv_axis_mm_times_1000[2]; // agv 坐标 乘1000返回 useful 原来的值单位是mm
  int32_t agv_angle_times_1000000;   // agv 角度 乘1000000返回 useful 原来的值单位是弧度

  uint8_t agv_global_state; // 主状态机 useful
  uint8_t agv_move_step;    // agv 运动的状态 useful
  uint8_t agv_connection_state;   // agv通信连接状态 useful
  uint8_t agv_sub_state3;   //! TODO

  int32_t machhead_position_mm_times_1000[2]; // 加工头坐标 乘1000返回 //! TODO
  int32_t secondlocate_camera_position_times_1000[2]; // 二次定位相机的坐标 mm
                                                      // 乘1000返回 useful

  uint8_t movetotarget_thread_status; // useful
  uint8_t initialposition_running_status; // useful
  uint8_t secondlocate_calcing_status; // useful
  uint8_t calculate_map_angle_status; // useful // TODO

  int32_t secondlocate_camera_position[2]; //! TODO 二次定位计算结果

  int32_t locate_confidence_times_1000; // 一次定位置信度 乘1000返回 useful
};

struct agvmodule_rx_secondLocateMovePlc_data_t {
  //    uint8_t is_timeout; // 超时标志位
  //    uint8_t precision_ok; // 精度到达
  //    uint8_t should_move; // 是否需要运动标志位
  //    uint8_t reserved;
  int error_code;

  int32_t axis1_inc;
  int32_t axis2_inc;
};

struct agvmodule_rx_initialPositionOnceOver_data_t {
  //    uint8_t is_timeout; // 超时标志位
  //    uint8_t reserved[3];
  int error_code;

  int32_t result_times_1000; // 标定精度
};

struct agvmodule_rx_calculateMapAngleResult_data_t {
  int error_code;
  int32_t points[4];
};
